package com.jauto.auto.core;

import com.jauto.auto.utils.ShellUtil;
import com.jauto.auto.utils.XmlUtil;
import com.jauto.auto.core.fc.DefultFuction;

import java.io.File;
import java.util.List;
import java.util.function.Function;

/**
 * 〈功能概述〉<br>
 *
 * @className: Device
 * @package: com.java.auto.core
 * @author: zhangRenHuo
 * @date: 2020/8/5 10:05
 */
public class Device {
    // 系统临时目录
    private String tempFile = System.getProperty("java.io.tmpdir");
    //设备号
    private String deviceCode;
    private XmlUtil xmlUtil = null;
    private boolean isCurrent = false;
    // 默认获取元素时间间隔 10 m秒
    private int defualtInterval = 2000;

    private static int second = 2000;
    private static final String space = " ";

    public String getDeviceCode() {
        return deviceCode;
    }


    public void setDeviceCode(String deviceCode) {
        this.deviceCode = deviceCode;
    }


    /*
     * @Description:
     * 获取界面xml信息 返回xml路径 获取元素时要先调用这个方法
     * @Author zhangRenHuo
     * @Date 10:52 2020/8/5
     * @return
     **/
    public Device find() {
        return select(()->shell("shell /system/bin/uiautomator dump /data/local/tmp/" + deviceCode.hashCode()+"uidump.xml"));
    }

    /*
     * 简洁的界面信息
     * @Author zhangRenHuo
     * @Date 17:35 2020/9/23
     * @param null
     * @return
     */
    public Device findMain() {
       return select(()->shell("shell /system/bin/uiautomator dump --compressed /data/local/tmp/" + deviceCode.hashCode()+"uidump.xml"));
    }

    private Device select(DefultFuction defultFuction){
        String fileName = deviceCode.hashCode()+"uidump.xml";
//        shell("shell rm -rf /data/local/tmp/"+fileName);
        defultFuction.start();
        String path = tempFile +fileName;
        shell("pull /data/local/tmp/"+fileName+" "+tempFile);
        if (null == xmlUtil){
            xmlUtil = new XmlUtil(path,deviceCode);
        }else {
            xmlUtil.reset(path);
        }
        return this;
    }

    public Device id(String id) throws InterruptedException {
        return defFunction(()-> xmlUtil.findById(id));
    }

    public Device parentId(String id) throws InterruptedException {
        return defFunction(()->xmlUtil.findByParentAndId(id));
    }

    public Device childId(String id) throws InterruptedException {
        return defFunction(()->xmlUtil.findByChildAndId(id));
    }
    
    public Device className(String className)throws InterruptedException{
        return defFunction(()->xmlUtil.findByClassName(className));
    }

    public Device parentClassName(String className)throws InterruptedException{
        return defFunction(()->xmlUtil.findByParentAndClassName(className));
    }

    public Device childClassName(String className)throws InterruptedException{
        return defFunction(()->xmlUtil.findByChildAndClassName(className));
    }

    public Device text(String text)throws InterruptedException{
        return defFunction(()->xmlUtil.findByText(text));
    }

    public Device parentText(String text)throws InterruptedException{
        return defFunction(()->xmlUtil.findByParentAndText(text));
    }

    public Device childText(String text)throws InterruptedException{
        return defFunction(()->xmlUtil.findByChildAndText(text));
    }

    public Device desc(String desc) throws InterruptedException{
        return defFunction(()->xmlUtil.findByDesc(desc));
    }

    public Device parentDesc(String desc) throws InterruptedException{
      return defFunction(()->xmlUtil.findByParentAndDesc(desc));
    }

    public Device childDesc(String desc) throws InterruptedException{
        return defFunction(()->xmlUtil.findByChildAndDesc(desc));
    }

    /*
     * @Description:
     * 获取子节点
     * @Author zhangRenHuo
     * @Date 17:26 2020/8/6
     * @return
     **/
    public Device child() throws InterruptedException{
        return defFunction(()->xmlUtil.getChild());
    }

    /*
     * @Description:
     * 根据子节点数查询 函数式
     * @Author zhangRenHuo
     * @Date 9:59 2020/8/6
     * @return
     **/
    public Device childNum(Integer num) throws InterruptedException{
       return defFunction(()->xmlUtil.findByChildNum(num));
    }

    /*
     * @Description:
     * 函数式接口调用
     * @Author zhangRenHuo
     * @Date 10:09 2020/8/6
     * @return
     **/
    private Device defFunction(DefultFuction defultFuction) throws InterruptedException {
//        boolean isOk = false;
//        int interval = this.defualtInterval;
//        while (!isOk) {
//            defultFuction.start();
//            if (xmlUtil.getElements().isEmpty()) {
//                find();
//                Thread.sleep(this.second);
//                interval += -this.second;
//                if (interval <= 0) {
//                    isOk = true;
//                }
//                continue;
//            }
//            // 避免未找到元素
////            defultFuction.start();
//            isOk = true;
//        }
        defultFuction.start();
        return this;
    }

    /*
     * @Description:
     * 根据条件最终返回对应的节点集合
     * @Author zhangRenHuo
     * @Date 9:32 2020/8/6
     * @return 
     **/
    public List<Node> getNodes(){
        return xmlUtil.getNodes();
    }

    //    0 2 1 3
    public void click(Integer x1,Integer x2,Integer y1,Integer y2){
        int x = (x1+x2)/2;
        int y = (y1+y2)/2;
        shell("shell input tap "+x+" "+y);
    }

    public void click(Integer x,Integer y){
        shell("shell input tap "+x+" "+y);
    }

    /*
     * @Description:
     * 滑动
     * @Author zhangRenHuo
     * @Date 10:18 2020/8/6
     * @return
     **/
    public void swipe(Integer startX,Integer startY,Integer endX,Integer endY){
        shell("shell input swipe"+space+startX+space+startY+ space+endX+space+endY+space+"500");
    }

    /*
     * @Description:
     * 滑动
     * @Author zhangRenHuo
     * @Date 10:18 2020/8/6
     * @return
     **/
    public void swipe(Integer startX,Integer startY,Integer endX,Integer endY,Integer ms){
        shell("shell input swipe"+space+startX+space+startY+ space+endX+space+endY+space+ms);
    }

    /*
     * @Description:
     * 根据包名加active路径启动app
     * @Author zhangRenHuo
     * @Date 15:27 2020/8/6
     * @return
     **/
    public void runApp(String packagePath){
        shell("shell am start -n "+packagePath);
    }

    /*
     * @Description:
     * 关闭app
     * @Author zhangRenHuo
     * @Date 15:30 2020/8/6
     * @return
     **/
    public void stopApp(String packageName){
        shell("shell am force-stop "+packageName);
    }

    public String listAppPackage(){
        return shell("shell pm list packages");
    }

    /*
     * @Description:
     * 获取设备分辨率
     * @Author zhangRenHuo
     * @Date 10:39 2020/8/6
     * @return
     **/
    public DeviceSize getSize(){
        String size = shell("shell wm size");
        String[] split = size.split(":");
        if (split.length>1){
            String[] xes = split[1].trim().split("x");
            DeviceSize deviceSize = new DeviceSize();
            deviceSize.setWidth(Integer.parseInt(xes[0]));
            deviceSize.setHeigth(Integer.parseInt(xes[1]));
            return deviceSize;
        }
        return null;
    }

    /*
     * @Description:
     * 获取设备id
     * @Author zhangRenHuo
     * @Date 10:47 2020/8/6
     * @return
     **/
    public String getAndroidId(){
        String androidId = shell("shell settings get secure android_id").trim();
        return androidId;
    }

    /*
     * 设置剪贴板内容
     * @Author zhangRenHuo
     * @Date 17:43 2020/9/23
     * @param null
     * @return
     */
    public void setClipper(String text){
        shell("shell am broadcast -a clipper.set -e text \""+text+"\"");
    }

    /**
     * 获取剪贴板内容
     * @Author zhangRenHuo
     * @Date 17:45 2020/9/23
     * @return
     */
    public String getClipper(){
        return shell("shell am broadcast -a clipper.get").trim();
    }

    /**
     * 左滑
     */
    public void leftSwipe(){
        DeviceSize size = getSize();
        swipe(size.getWidth()/2,size.getHeigth()/2,0,size.getHeigth()/2);
    }

    /**
     * 右滑
     */
    public void rightSwipe(){
        DeviceSize size = getSize();
        swipe(0,size.getHeigth()/2,size.getWidth(),size.getHeigth()/2);
    }

    /**
     * 上滑
     */
    public void topSwipe(){
        DeviceSize size = getSize();
        swipe(size.getWidth()/2,size.getHeigth()/2,size.getWidth()/2,0);
    }

    /**
     * 下滑
     */
    public void bottomSwipe(){
        DeviceSize size = getSize();
        swipe(size.getWidth()/2,size.getHeigth()/2,size.getWidth()/2,size.getHeigth());
    }

    /**
     * 返回
     */
    public void back(){
        shell("shell input keyevent 4").trim();
    }

    /**
     * 模拟输入key
     * @param key
     */
    public void key(String key){
        shell("shell input keyevent "+key);
    }

    /**
     * 设置代理ip  如：192.168.1.200:3128
     * @Author zhangRenHuo
     * @Date 14:38 2020/10/12
     * @param proxy
     * @return
     */
    public void setProxy(String proxy){
        shell("shell settings put global http_proxy "+proxy);
    }

    /**
     * 去掉ip代理
     * @Author zhangRenHuo
     * @Date 14:40 2020/10/12
     * @return
     */
    public void cancelProxy(){
        shell("shell settings delete global http_proxy");
        shell("shell settings delete global global_http_proxy_host");
        shell("shell settings delete global global_http_proxy_port");
        shell("reboot");
    }

    /**
     * 截图 -- 图片路径
     * @Author zhangRenHuo
     * @Date 15:28 2020/10/15
     * @return
     */
    public String screencap(){
        String filePath = tempFile+deviceCode +"img.png";
        File file = new File(filePath);
        if (file.exists()){
            boolean delete = file.delete();
        }
        shell("shell screencap -p /data/local/tmp/" + deviceCode+ "img.png" );
        shell("pull /data/local/tmp/"+deviceCode +"img.png "+tempFile);
        return filePath;
    }

    /*
     * @Description:
     * 执行adb命令
     * @Author zhangRenHuo
     * @Date 10:39 2020/8/5
     * @return
     **/
    private String shell(String adb){
        Process cmd = ShellUtil.cmd("-s " + deviceCode + " " + adb);
        String shellOut = ShellUtil.getShellOut(cmd);
        return shellOut;
    }

    private static void err(String str){
        System.err.println(str);
    }
    private Device(){}

    public static Device getDevice(String id){
        Device device = new Device();
        device.setDeviceCode(id);
        return device;
    }

    public String getTempFile() {
        return tempFile;
    }

    public class DeviceSize{
        private Integer width;
        private Integer heigth;

        public Integer getWidth() {
            return width;
        }

        public void setWidth(Integer width) {
            this.width = width;
        }

        public Integer getHeigth() {
            return heigth;
        }

        public void setHeigth(Integer heigth) {
            this.heigth = heigth;
        }
    }

}
